#include "mainwidget.h"
#include "./ui_mainwidget.h"

#include "model/data.h"
#include "model/datacenter.h"
#include "Debug.h"
#include "sessiondetailwidget.h"
#include "groupsessiondetailwidget.h"
#include "addfrienddialog.h"

MainWidget::MainWidget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::MainWidget)
{
    ui->setupUi(this);

    setWindowTitle("我的聊天室");
    setWindowIcon(QIcon(":/resource/image/logo.png"));

    initUI();
    initSlot();
    initWebSocket();
}

void MainWidget::initUI()
{
    initMainWindow();
    initLeftWindow();
    initMidWindow();
    initRightWindow();
}

void MainWidget::initMainWindow()
{
    QHBoxLayout* layout = new QHBoxLayout();
    layout->setSpacing(0);
    layout->setContentsMargins(0, 0, 0, 0);
    setLayout(layout);

    m_leftWidget = new QWidget();
    m_midWidget = new QWidget();
    m_rightWidget = new QWidget();

    m_leftWidget->setObjectName("windowLeft");
    m_midWidget->setObjectName("windowMid");
    m_rightWidget->setObjectName("windowRight");

    m_leftWidget->setFixedWidth(70);
    m_midWidget->setFixedWidth(200);
    m_rightWidget->setMinimumWidth(450);

    layout->addWidget(m_leftWidget);
    layout->addWidget(m_midWidget);
    layout->addWidget(m_rightWidget);

    QString style = "#windowLeft { background-color: #2E2E2E; }"
                    "#windowMid { background-color: #F7F7F7; }"
                    "#windowRight {background-color: #F5F5F5; }";
    this->setStyleSheet(style);
}

void MainWidget::initLeftWindow()
{
    QVBoxLayout* layout = new QVBoxLayout();
    m_leftWidget->setLayout(layout);
    layout->setSpacing(20);

    m_userAvatar = new QPushButton();
    // m_userAvatar->setIcon(QIcon(":/resource/image/defaultAvatar2.jpg"));
    m_userAvatar->setFixedSize(45, 45);
    m_userAvatar->setIconSize(QSize(45, 45));
    m_userAvatar->setStyleSheet("QPushButton { background-color: transparent;}");
    m_userAvatar->setCursor(Qt::PointingHandCursor);

    m_sessionTabBtn = new QPushButton();
    m_sessionTabBtn->setIcon(QIcon(":/resource/image/session_active.png"));
    m_sessionTabBtn->setFixedSize(30, 30);
    m_sessionTabBtn->setIconSize(QSize(30, 30));
    m_sessionTabBtn->setStyleSheet("QPushButton { background-color: transparent;}");


    m_friendTabBtn = new QPushButton();
    m_friendTabBtn->setIcon(QIcon(":/resource/image/friend_inactive.png"));
    m_friendTabBtn->setFixedSize(30, 30);
    m_friendTabBtn->setIconSize(QSize(30, 30));
    m_friendTabBtn->setStyleSheet("QPushButton { background-color: transparent;}");

    m_applyTabBtn = new QPushButton();
    m_applyTabBtn->setIcon(QIcon(":/resource/image/apply_inactive.png"));
    m_applyTabBtn->setFixedSize(30, 30);
    m_applyTabBtn->setIconSize(QSize(30, 30));
    m_applyTabBtn->setStyleSheet("QPushButton { background-color: transparent;}");

    layout->addWidget(m_userAvatar, 1, Qt::AlignTop | Qt::AlignHCenter);
    layout->addWidget(m_sessionTabBtn, 1, Qt::AlignTop | Qt::AlignHCenter);
    layout->addWidget(m_friendTabBtn, 1, Qt::AlignTop | Qt::AlignHCenter);
    layout->addWidget(m_applyTabBtn, 1, Qt::AlignTop | Qt::AlignHCenter);
    // 控制layout的拉伸空间的拉伸系数。下⽅添加空隙, 把上述控件挤上去.
    layout->addStretch(10);
}

void MainWidget::initMidWindow()
{
    QGridLayout* layout = new QGridLayout();
    m_midWidget->setLayout(layout);
    layout->setContentsMargins(0, 20, 0, 0);
    layout->setVerticalSpacing(10);    // 垂直间距为0
    // layout->setSpacing(0);

    m_searchEdit = new QLineEdit();
    m_searchEdit->setFixedHeight(25);
    m_searchEdit->setPlaceholderText("搜索");
    m_searchEdit->setStyleSheet("QLineEdit{ border-radius: 5px; background-color: rgb(226,226,226); padding-left: 5px;}");

    m_addFriendBtn = new QPushButton();
    m_addFriendBtn->setFixedSize(25, 25);
    m_addFriendBtn->setIcon(QIcon(":/resource/image/cross.png"));
    QString style = "QPushButton{ border-radius:5px; background-color: rgb(226,226,226)}"
                    "QPushButton:pressed { background-color: rgb(240, 240, 240); } ";
    m_addFriendBtn->setStyleSheet(style);

    QWidget* space1 = new QWidget();
    QWidget* space2 = new QWidget();
    QWidget* space3 = new QWidget();
    space1->setFixedWidth(10);
    space2->setFixedWidth(10);
    space3->setFixedWidth(10);

    layout->addWidget(space1, 0, 0);
    layout->addWidget(m_searchEdit, 0, 1);
    layout->addWidget(space2, 0, 2);
    layout->addWidget(m_addFriendBtn, 0, 3);
    layout->addWidget(space3, 0, 4);

    m_sessionFriendArea = new SessinoFriendArea();
    layout->addWidget(m_sessionFriendArea, 1, 0, 1, 5);
}

void MainWidget::initRightWindow()
{
    // 整体垂直向下
    QVBoxLayout* vlayout = new QVBoxLayout();
    m_rightWidget->setLayout(vlayout);
    vlayout->setContentsMargins(0, 0, 0, 0);
    vlayout->setSpacing(0);
    vlayout->setAlignment(Qt::AlignTop);

    // 1. 标题名称 和 更多信息
    QWidget* widget = new QWidget();
    vlayout->addWidget(widget);
    widget->setFixedHeight(55);
    widget->setStyleSheet("QWidget { "
                          "border-bottom: 1px solid rgb(231,231, 231); "
                          "border-left: 1px solid rgb(231, 231, 231); }");

    QHBoxLayout* hlayout = new QHBoxLayout();
    widget->setLayout(hlayout);
    hlayout->setContentsMargins(20, 0, 20, 0);
    hlayout->setSpacing(0);

    m_sessionTitle = new QLabel();
    m_sessionTitle->setStyleSheet("QLabel {font-size: 18px;}");
    // m_sessionTitle->setCursor(Qt::PointingHandCursor);
#if TEST_UI
    m_sessionTitle->setText("测试标题");
#endif

    m_more = new QPushButton();
    m_more->setFixedSize(30, 30);
    m_more->setIcon(QIcon(":/resource/image/more.png"));
    m_more->setStyleSheet("QPushButton {background-color: rgb(240, 240, 240); border:none;}"
                          "QPushButton:pressed {background-color: rgb(230, 230, 230);}"
                          );
    m_more->setCursor(Qt::PointingHandCursor);
    hlayout->addWidget(m_sessionTitle);
    hlayout->addWidget(m_more);

    // 2. 消息框
    m_messageShowArea = new MessageShowArea();
    vlayout->addWidget(m_messageShowArea);

    // 3. 编辑框
    m_messageEditArea = new MessageEditArea();
    vlayout->addWidget(m_messageEditArea, 0, Qt::AlignBottom);
}

void MainWidget::initSlot()
{
    model::DataCenter* dataCenter = model::DataCenter::getInstance();

    connect(m_sessionTabBtn, &QPushButton::clicked, this, &MainWidget::switchTabToSession);
    connect(m_friendTabBtn, &QPushButton::clicked, this, &MainWidget::switchTabToFriend);
    connect(m_applyTabBtn, &QPushButton::clicked, this, &MainWidget::switchTabToApply);

    connect(m_userAvatar, &QPushButton::clicked, this, [=]{
        m_selfInfo = new SelfInfoWidget(dataCenter->getMyself(), this);
        m_selfInfo->exec();
    });

    connect(m_more, &QPushButton::clicked, this, [=]{
#if TEST_GROUP_SESSION_DETAIL
        SessionDetailWidget* sessionDetail = new SessionDetailWidget();
        sessionDetail->exec();
#endif
        model::DataCenter* dataCenter = model::DataCenter::getInstance();
        auto chat = dataCenter->findChatSessionBySessionId(dataCenter->getCurrentChatSessionId());
        if(chat == nullptr){
            LOG() << "会话未选中";
            return;
        }
        // 群聊
        if(chat->m_userId == ""){
            GroupSessionDetailWidget* groupSessionDetail = new GroupSessionDetailWidget();
            groupSessionDetail->exec();
        }else{
            // 单聊
            // 对方信息
            auto user = dataCenter->getFriendById(chat->m_userId);
            SessionDetailWidget* sessionDetail = new SessionDetailWidget(*user);
            sessionDetail->exec();
        }

    });

    connect(m_addFriendBtn, &QPushButton::clicked, this, [=]{
        AddFriendDialog* addFriendDialog = new AddFriendDialog();
        addFriendDialog->exec();
    });

    // 不可用 QLineEdit::textChanged 因为里面会调用 setText()，造成死循环
    connect(m_searchEdit, &QLineEdit::textEdited, this, [=]{
        AddFriendDialog* addFriendDialog = new AddFriendDialog();
        // 获取到输⼊框内容并清空
        const QString& text = m_searchEdit->text();
        m_searchEdit->setText("");
        addFriendDialog->getLineEdit()->setText(text);
        addFriendDialog->exec();
    });

    // 获取个人信息时 更新头像
    connect(dataCenter, &model::DataCenter::getMyselfDone, this, [=]{
        m_userAvatar->setIcon(dataCenter->getMyself()->m_avatar);
    });
    // 修改头像时 更新头像
    connect(dataCenter, &model::DataCenter::changeAvatarDone, this, [=]{
        m_userAvatar->setIcon(dataCenter->getMyself()->m_avatar);
    });
    // 删除好友时 更新会话和好友列表
    connect(dataCenter, &model:: DataCenter::deleteFriendDone, this, [=]{
        this->updateFriendList();
        this->updateSessionList();
        LOG() << "成功删除好友";
    });
    // 删除好友时，如果是当前会话，则清空聊天记录
    connect(dataCenter, &model::DataCenter::clearCurrentSession, this, [=]{
        m_sessionTitle->setText("");  // 标题置空
        m_messageShowArea->clear();   // 聊天记录清空
        dataCenter->setCurrentChatSessionId("");
        LOG() << "删除好友为当前会话, 清空完成";
    });
    // 发送好友申请时，更新好友申请界面
    connect(dataCenter, &model::DataCenter::receiveFriendApplyDone, this, &MainWidget::updateApplyList);
    // 收到好友申请时，更新好友界面
    connect(dataCenter, &model::DataCenter::receiveFriendProcessAccept, this, &MainWidget::updateFriendList);
    // 同意好友申请时，更新好友，好友申请界面
    connect(dataCenter, &model::DataCenter::acceptFriendApplyDone, this, [=]{
        this->updateApplyList();
        this->updateFriendList();
    });
    // 收到新的会话，更新会话列表数据
    connect(dataCenter, &model::DataCenter::receiveSessionCreateDone, this, &MainWidget::updateSessionList);

    // 获取个人信息
    dataCenter->getMyselfAsync();
    // 获取会话信息列表
    loadSessionList();
    // 获取好友信息列表
    loadFriendList();
    // 获取好友申请列表
    loadApplyList();
}

void MainWidget::initWebSocket()
{
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    dataCenter->initWebsocket();
}

void MainWidget::switchTabToSession()
{
    LOG() << "会话消息 界面被选中";
    m_activeTab = SESSION_LIST;
    // 1.更换样式
    m_sessionTabBtn->setIcon(QIcon(":/resource/image/session_active.png"));
    m_friendTabBtn->setIcon(QIcon(":/resource/image/friend_inactive.png"));
    m_applyTabBtn->setIcon(QIcon(":/resource/image/apply_inactive.png"));
    // 2.加载会话页面数据
    loadSessionList();
}

void MainWidget::switchTabToFriend()
{
    LOG() << "好友列表 界面被选中";
    m_activeTab = FRIEND_LIST;
    // 1.更换样式
    m_sessionTabBtn->setIcon(QIcon(":/resource/image/session_inactive.png"));
    m_friendTabBtn->setIcon(QIcon(":/resource/image/friend_active.png"));
    m_applyTabBtn->setIcon(QIcon(":/resource/image/apply_inactive.png"));
    // 2.加载好友页面数据
    loadFriendList();
}

void MainWidget::switchTabToApply()
{
    LOG() << "好友申请 界面被选中";
    m_activeTab = APPLY_LIST;
    // 1.更换样式
    m_sessionTabBtn->setIcon(QIcon(":/resource/image/session_inactive.png"));
    m_friendTabBtn->setIcon(QIcon(":/resource/image/friend_inactive.png"));
    m_applyTabBtn->setIcon(QIcon(":/resource/image/apply_active.png"));
    // 2.加载好友申请页面数据
    loadApplyList();
}

void MainWidget::loadSessionList()
{
    // 有本地数据就先加载本地数据
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    const QList<model::chatSessionInfo>* chatSessionList = dataCenter->getChatSessionList();
    if(chatSessionList){
        updateSessionList();
    }else{
        // 没有本地数据，就从服务器上获取
        // 加载好友列表
        connect(dataCenter, &model::DataCenter::getChatSessionListDone, this, &MainWidget::updateSessionList, Qt::UniqueConnection);
        dataCenter->getChatSessionListAsync();
    }
}

void MainWidget::loadFriendList()
{
    // 有本地数据就先加载本地数据
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    const QList<UserInfo>* friendList = dataCenter->getFriendList();
    if(friendList){
        updateFriendList();
    }else{
        // 没有本地数据，就从服务器上获取
        // 加载好友列表
        connect(dataCenter, &model::DataCenter::getFriendListDone, this, &MainWidget::updateFriendList, Qt::UniqueConnection);
        dataCenter->getFriendListAsync();
    }
}

void MainWidget::loadApplyList()
{
    // 有本地数据就先加载本地数据
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    const QList<UserInfo>* applyList = dataCenter->getApplyList();
    if(applyList){
        updateApplyList();
    }else{
        connect(dataCenter, &model::DataCenter::getApplyListDone, this, &MainWidget::updateApplyList, Qt::UniqueConnection);
        dataCenter->getApplyListAsync();
    }
}

void MainWidget::updateSessionList()
{
    if(m_activeTab != ActiveTab::SESSION_LIST){
        return ;
    }
    m_sessionFriendArea->clear();

    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    auto chatSessionList = dataCenter->getChatSessionList();
    for(const auto& chat : *chatSessionList){
        if(chat.m_message.m_type == model::TEXT_TYPE){
            m_sessionFriendArea->addItem(ITEMTYPE::SESSIONITEMTYPE, chat.m_chatSessionId, chat.m_avatar,
                                         chat.m_chatSessionName, chat.m_message.m_content);
        }else if(chat.m_message.m_type == model::IMAGE_TYPE){
            m_sessionFriendArea->addItem(ITEMTYPE::SESSIONITEMTYPE, chat.m_chatSessionId, chat.m_avatar,
                                         chat.m_chatSessionName, "[图片]");
        }else if(chat.m_message.m_type == model::FILE_TYPE){
            m_sessionFriendArea->addItem(ITEMTYPE::SESSIONITEMTYPE, chat.m_chatSessionId, chat.m_avatar,
                                         chat.m_chatSessionName, "[文件]");
        }else if(chat.m_message.m_type == model::SPEECH_TYPE){
            m_sessionFriendArea->addItem(ITEMTYPE::SESSIONITEMTYPE, chat.m_chatSessionId, chat.m_avatar,
                                         chat.m_chatSessionName, "[语言]");
        }else{
            LOG() << "未知类型：" << chat.m_message.m_type;
        }
    }

}

void MainWidget::updateFriendList()
{
    if(m_activeTab != ActiveTab::FRIEND_LIST){
        return ;
    }
    m_sessionFriendArea->clear();

    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    const QList<UserInfo>* friendList = dataCenter->getFriendList();

    for(const auto& user : *friendList){
        m_sessionFriendArea->addItem(ITEMTYPE::FRIENDITEMTYPE, user.m_userId,
                                     user.m_avatar, user.m_nickName, user.m_description);
    }
}

void MainWidget::updateApplyList()
{
    if(m_activeTab != APPLY_LIST){
        return ;
    }else{
        m_sessionFriendArea->clear();
    }

    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    const QList<UserInfo>* applyList = dataCenter->getApplyList();
    for(const auto& a : *applyList){
        m_sessionFriendArea->addItem(APPLYITEMTYPE, a.m_userId, a.m_avatar, a.m_nickName, "");
    }
}

void MainWidget::updateRecentMessages(const QString &chatSessionId)
{
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    const QList<Message>* msgList = dataCenter->getRecentMsgList(chatSessionId);

    // 清空原有的消息列表
    m_messageShowArea->clear();

    // 消息头插，把最新消息发在最前的
    for(int i = msgList->size()- 1; i >= 0; --i){
        const Message& msg = msgList->at(i);
        bool isLeft = dataCenter->getMyself()->m_userId != msg.m_sender.m_userId;
        m_messageShowArea->addFrontMessage(isLeft, msg);
    }

    // 设置会话标题
    auto chatSessionInfo = dataCenter->findChatSessionBySessionId(chatSessionId);
    if(chatSessionInfo){
        m_sessionTitle->setText(chatSessionInfo->m_chatSessionName);
    }

    // 设置为当前会话，后续发送信息之类的消息都在此会话区域
    dataCenter->setCurrentChatSessionId(chatSessionId);
    LOG() << "当前会话的id" << chatSessionId;

    m_messageShowArea->scrollToEndLater();
}

MainWidget *MainWidget::getInstance()
{
    static MainWidget mainwidget;
    return &mainwidget;
}

void MainWidget::loadRecentMessages(const QString &chatSessionId)
{
    // 本地有数据就先加载数据
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    const QList<Message>* recentMsg = dataCenter->getRecentMsgList(chatSessionId);
    if(recentMsg){
        updateRecentMessages(chatSessionId);
    }else{
        connect(dataCenter, &model::DataCenter::getRecentMsgListDone, this, &MainWidget::updateRecentMessages, Qt::UniqueConnection);
        dataCenter->getRecentMsgListAsync(chatSessionId, true);
    }
}

void MainWidget::switchToSession(const QString &userId)
{
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    // 1. 先根据好友 id 找到对应的会话
    model::chatSessionInfo* chat = dataCenter->findChatSessionByUserId(userId);

    // 2. 把会话置顶
    if(chat)
        dataCenter->topChatSessionInfo(*chat);
    else{
        LOG() << "找不到该对话";
        return ;
    }

    // 3. 切换到会话标签⻚
    switchTabToSession();

    // 4. 点击⼀下这个会话
    m_sessionFriendArea->clickItem(0);
}

MainWidget::~MainWidget()
{
    delete ui;
}
